/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Rutas;

import java.io.IOException;
import java.io.Reader;
import java.util.*;
/**
 *
 * @author Usuario
 */
public class NedWun {
    private List<Paradero> seq1;//ruta esperada
    private List<Paradero> seq2;//ruta obtenida
    public int[][] matrix;/*matriz de scores*/
    public int[][] rastreo;
    private int gap;
    private int error;
    private int match;
    private List<Paradero> fiSeq1;//ruta ideal al final de la alineacion
    private List<Paradero> fiSeq2;//ruta obtenida al final de la alineacion
    
    public NedWun(List<Paradero> s1,List<Paradero> s2){
        this.seq1 = s1;
        this.seq2 = s2;
        this.gap = 0;
        this.error = -1;
        this.match = 1;
    }
    
    public List<Paradero> getSeq1(){
        return this.seq1;
    }
    
    public List<Paradero> getSeq2(){
        return this.seq2;
    }
    
    public void setSeq1(List<Paradero> s){
        this.seq1 = s;
    }
    
    public void setSeq2(List<Paradero> s){
        this.seq2 = s;
    }
    
    private int maximo(int op1, int op2){
        if(op1>op2){
            return op1;
        }
        else
            return op2;
    }
    
    public void creaMatrix(){
        int i,j, match;
        int op1, op2, op3;
        int fil = seq2.size()+1;
        int col = seq1.size()+1;
        
        matrix = new int[fil][col];
        rastreo = new int[fil][col];
        
        
        for (i=0;i<fil;i++){
            for(j=0;j<col;j++){
                if((i==0)||(j==0)){
                    if((i==0)&&(j==0)){
                        matrix[0][0] = 0;
                    }
                    else
                        matrix[i][j] = this.error;
                }
                else{/*entonce si se calcula el nuevo score*/
                    if(seq1.get(j-1).getIdParadero()==seq2.get(i-1).getIdParadero()){
                        match = this.match;//el valor por el match                      
                    }
                    else
                        match = this.error;
                    /*Consideramos las 3 opciones*/
                    op1 = matrix[i-1][j-1] + match;
                    op2 = matrix[i-1][j] + this.gap;/*secuencia 2*/
                    op3 = matrix[i][j-1] + this.gap;/*secuencia 1*/
                    
                    matrix[i][j] = maximo(maximo(op1,op2),op3);
                    
                    if(matrix[i][j]==op1)
                        rastreo[i][j]=0;
                    else if(matrix[i][j]==op2)
                            rastreo[i][j]=1;
                    else
                        rastreo[i][j]=-1;                       
                }
            }
        }
    }
    
    public void rastrea(){
        int l1, l2;
        List<Paradero> fSeq1, fSeq2;
        Paradero aux;
        
        fSeq1 = new ArrayList<Paradero>();
        fSeq2 = new ArrayList<Paradero>();
        aux = new Paradero();
        aux.setIdParadero((char)1);
        
        l1 = this.seq1.size();
        //System.out.println(""+l1);
        l2 = this.seq2.size();
        //System.out.println(""+l2);
        while((l1>0)&&(l2>0)){
            if(rastreo[l2][l1]==0){
                fSeq1.add(seq1.get(l1-1));
                fSeq2.add(seq2.get(l2-1));
                l1=l1-1;
                l2=l2-1;
            }
            else{
                if(rastreo[l2][l1]==1){
                    fSeq2.add(seq2.get(l2-1));
                    fSeq1.add(aux);
                    l2 = l2 - 1;
                }
                else{
                    fSeq2.add(aux);
                    fSeq1.add(seq1.get(l1-1));
                    l1 = l1 - 1;
                }
            }
        }
        this.fiSeq1 = fSeq1;
        this.fiSeq2 = fSeq2;
    }
    
    public float fObj(Paradero a){
        float valor, num, den;
        num = 3*a.getPromSuben();
        den = 10*a.getVelPromedio()+(a.getTiempoEspera()+a.getTiempoLlegada());
        valor = num/den;
        return valor;
    }
    
    public int comparaPatron(int i){
        //devuelve 1 si no se cumple el patron
        //devuelve 0 si se cumple el patron
        float f1, f2; //es el valor objetivo de las cadenas
        f1 = fObj(this.fiSeq1.get(i));/*ideal*/
        f2 = fObj(this.fiSeq2.get(i));/*esperado*/
        
        if((f2>=(0.90*f1))&&(f2<=(1.10*f1))){
            //se otorga un 10% de rango de aceptación
            //cumple el patrón
            return 0;
        }
        //no cumple patron
        return 1;
    }
    
    public int compara(){
        int cantParE = 0;//cantidad de paraderos a los que fue equivocadamente
        int cantParS = 0;//cantidad de paraderos saltados
        int cantPatE = 0;//cantidad de incumplimiento de patrones
        for(int i=0; i<this.fiSeq1.size();i++){
            if((fiSeq1.get(i).getIdParadero()==((char)1))){
                cantParE = cantParE + 1;
            }
            else{
                if(fiSeq2.get(i).getIdParadero()==((char)1)){
                    cantParS = cantParS + 1;
                }
                else{
                    if(fiSeq2.get(i).getIdParadero()==fiSeq1.get(i).getIdParadero()){
                        cantPatE = cantPatE + comparaPatron(i);                        
                    }
                    else{
                        cantParE = cantParE + 1;
                    }
                }
            }
        }
        //System.out.println("Cantidad de Paraderos Equivocados: " + cantParE);
        //System.out.println("Cantidad de Paraderos Omitidos: " + cantParS);
        //System.out.println("Cantidad de Incumplimiento de Patrón: " + cantPatE);
        //System.out.println("Cantidad de Incidencias: " + (cantParE+cantParS+cantPatE));
        return (cantParE+cantParS+cantPatE);
    }
    
    public void imprimeRut(){
        System.out.println("Ruta Deseada");
        for(int i=this.seq1.size(); i>0;i--){
            System.out.print(""+this.seq1.get(i-1).getIdParadero());
        }
        System.out.println();
        System.out.println("Ruta Obtenida");
        for(int i=this.seq2.size(); i>0;i--){
            System.out.print(""+this.seq2.get(i-1).getIdParadero());
        }
        System.out.println();
        System.out.println("Ruta Deseada Final");
        for(int i=0; i<this.fiSeq1.size();i++){
            System.out.print(""+this.fiSeq1.get(i).getIdParadero());
        }
        System.out.println();
        System.out.println("Ruta Obtenida Final");
        for(int i=0; i<this.fiSeq2.size();i++){
            System.out.print(""+this.fiSeq2.get(i).getIdParadero());
        }
        System.out.println();
    }
    
    public int algoritmo(){
        creaMatrix();
        rastrea();
        //imprimeRut();
        return compara();
    }
}
